from typing import Generic, TypeVar
from pydantic import BaseModel
from sqlalchemy import and_, insert, select, update
from forward.common.enums import CodeStatusEnum
from forward.dependencies.database import db
from forward.model.schemas.lucky.code import CodeCreateSchema, CodeOutSchema
from forward.model.tables.activity import ActivityModel, CodeModel, PrizeModel
from forward.model.tables.merchant import MerchantModel
from forward.utils.page_utils import PageSchema, PageUtils

# 定义一个泛型类型变量
T = TypeVar("T", bound=BaseModel)


class CodeORM(Generic[T]):

    async def get_one_by_id(self, id: int) -> CodeOutSchema | None:
        statement = select(CodeModel).where(CodeModel.id == id)
        record = await db.fetch_one(statement)
        if not record:
            return None
        return CodeOutSchema.model_validate(record, from_attributes=True)

    async def get_lists_by_activity_id(
        self, activity_id: int, status: CodeStatusEnum
    ) -> list[CodeOutSchema]:
        statement = (
            select(CodeModel)
            .where(CodeModel.activity_id == activity_id)
            .where(CodeModel.status == status.value)
        )
        records = await db.fetch_all(statement)
        if not records:
            return []
        return [
            CodeOutSchema.model_validate(record, from_attributes=True)
            for record in records
        ]

    async def get_one_by_filters(self, **kwargs) -> CodeOutSchema | None:
        where = []
        for key, value in kwargs.items():
            if not hasattr(CodeModel, key):
                continue  # 跳过不存在的字段
            where.append(getattr(CodeModel, key) == value)

        statement = select(CodeModel).where(and_(*where))
        record = await db.fetch_one(statement)

        if not record:
            return None
        return CodeOutSchema.model_validate(record, from_attributes=True)

    async def create(self, code_in: CodeCreateSchema):
        statement = insert(CodeModel).values(**code_in.model_dump())
        record = await db.execute(statement)
        return record

    @classmethod
    async def update(cls, id: int, **kwargs):
        for key, value in kwargs.items():
            if hasattr(CodeModel, key):
                kwargs[key] = value
        statement = update(CodeModel).where(CodeModel.id == id).values(**kwargs)
        record = await db.execute(statement)

        return record

    @classmethod
    async def lists(
        cls,
        page_num: int,
        page_size: int,
        where: list = [],
    ) -> PageSchema[CodeOutSchema]:
        print("where", where)
        statement = (
            select(
                CodeModel,
                PrizeModel.name.label("prize_name"),
                MerchantModel.name.label("merchant"),
                ActivityModel.title.label("activity_title"),
            )
            .where(*where)
            .outerjoin(PrizeModel, CodeModel.prize_id == PrizeModel.id)
            .outerjoin(ActivityModel, CodeModel.activity_id == ActivityModel.id)
            .outerjoin(MerchantModel, ActivityModel.merchant_id == MerchantModel.id)
            .order_by(CodeModel.id.desc())
        )
        pagination = await PageUtils.paginate(
            db=db,
            query=statement,
            page_num=page_num,
            page_size=page_size,
            schema=CodeOutSchema,
        )
        return pagination
